package read;

import java.io.*;

/**
 * @author Zerone
 * date: 2016/11/2
 *
 * Audio read module: read a wav file, verify it and get time domain data.
 */

public class AudioRead {
    private FileInputStream inputStream;
    private String path;
    private byte[] head = new byte[46];
    private byte[] data;
    private double[] sequence;

    public AudioRead(String path) {
        this.path = path;
        input();
        toDouble();
    }

    public void input() {
        try {
            inputStream = new FileInputStream(path);
            inputStream.read(head);

            // Subchunk2_size: 42,43,44,45
            int length = (((head[45] << 8) | (head[44] & 0xff)) << 16)
                    | (((head[43] << 8) | (head[42] & 0xff)) & 0xffff);

            data = new byte[length];
            inputStream.read(data);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * To verify if the file's format is RIFF
     */
    public boolean ifRIFF() {
        boolean ret = true;
        if (head[0] != 'R' || head[1] != 'I'
                || head[2] != 'F' || head[3] != 'F') {
            ret = false;
        }
        return ret;
    }

    /**
     * To verify if the file's format is PCM
     */
    public boolean ifPCM() {
        boolean ret = true;
        if (head[20] != 1 || head[21] != 0) {
            ret = false;
        }
        return ret;
    }

    /**
     *  To verify if the wav file has only one channel
     */
    public boolean ifSingleChannel() {
        boolean ret = true;
        if (head[22] != 1 || head[23] != 0) {
            ret = false;
        }
        return ret;
    }

    /**
     * To verify if the sample rate is 44100 Hz
     */
    public boolean verifySampleRate() {
        boolean ret = true;
        if (head[24] != 68 || head[25] != -84 || head[26] != 0 || head[27] != 0) {
            ret = false;
        }
        return ret;
    }

    /**
     * To verify if the bits per sample is 16 bit
     */
    public boolean verifyBitsPerSample() {
        boolean ret = true;
        if (head[34] != 16 || head[35] != 0) {
            ret = false;
        }
        return ret;
    }

    /**
     * convert byte[] to double[]
     */
    public void toDouble() {
        int p = 0;
        short[] temp = new short[data.length / 2];
        sequence = new double[data.length / 2];

        for (int i = 0; i < data.length; i += 2) {
            temp[p] = (short) ((data[i + 1] << 8) | (data[i] & 0xff));
            ++p;
        }

        for (int i = 0; i < temp.length; ++i) {
            sequence[i] = (double) temp[i];
        }
        return;
    }

    public void output() {
        PrintWriter out = null;
        try {
            out = new PrintWriter(new FileWriter(new File("doc/김지현 - 오나라Ⅱ.wav")));
        } catch (IOException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < sequence.length; ++i) {
            out.printf("%.2f,\n", sequence[i]);
        }
        out.close();
    }

    public double[] getSequence() {
        return sequence;
    }

    public static void main(String[] args) {
        AudioRead test = new AudioRead("doc/김지현 - 오나라Ⅱ.wav");
        System.out.println("if RIFF: " + test.ifRIFF());
        System.out.println("if PCM: " + test.ifPCM());
        System.out.println("if single channel: " + test.ifSingleChannel());
        System.out.println("bits per sample: " + test.verifyBitsPerSample());
        System.out.println("sample rate: " + test.verifySampleRate());
        test.output();
    }
}
